package com.suse.lhw.hms.authorizaiontserver.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ProjectName: health_manage_system
 * @Package: com.suse.lhw.security.config
 * @ClassName: ControllerLogAspect
 * @Description: 实现打印controller的配置类，具体用法如下：
 * @RestController
 * @RequestMapping("/log")
 * @Slf4j public class LogController {
 * @PostMapping("/qsm")
 * @ControllerMethodTitle("我是一个可爱的测试获取qsm的接口") public Qsm2 http(@RequestBody @Valid Qsm2 qsm2, HttpServletRequest request) {
 * log.info("\n    [处理中], 程序正在处理请求逻辑");
 * return qsm2;
 * }
 * }
 * @Author: 李鸿炜
 * @CreateDate: 2021/2/12 13:38
 * @UpdateUser: 更新者
 * @UpdateDate: 2021/2/12 13:38
 * @UpdateRemark: 更新说明
 * @Version: 1.0
 */
@Component
@Aspect
@Slf4j
@Order(-98)
public class ControllerLogAspect {
    @Autowired
    HttpServletRequest request;

    /**
     * 【注意】 修改为你自己项目中controller层路径
     */
    @Pointcut("execution(public * com.suse.lhw.security.controller..*.*(..))")
    public void pointcut() {
    }

    public String randomString(double randomNumber) {
        String[] strings = {
                "向你说句新年快乐！！！",
                "希望你新的一年里牛气冲天！！！",
                "祝愿你身体健康！！！",
                "祝福你对牛年bug说拜拜！！！",
                "给你发了微信红包，但这只是ide控制台你没有办法收取！！！",
                "还躺在床上并不想给你发新年祝福！！！",
                "想给你发祝福但它自己出了bug，给你帮了倒忙！！！",
                "祝你牛年牛子变大！！！",
                "祝你新年快乐！"
        };
        return strings[(int) Math.floor(randomNumber * (strings.length - 1))];
    }

    @Around("pointcut()")
    public Object handle(ProceedingJoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        //请求controller名称，使用@ControllerMethodTitle注解

//        String controllerTitle = getControllerMethodTitle(joinPoint);

        String controllerTitle = joinPoint.getSignature().getName() + "接口" + this.randomString(Math.random());
        //方法路径
        String methodName = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        //IP地址
        String iP = getIp(request);
        //请求入参
        String requestParam = JSON.toJSONString(Arrays.stream(joinPoint.getArgs())
                .filter(param -> !(param instanceof HttpServletRequest)
                        && !(param instanceof HttpServletResponse)
                        && !(param instanceof MultipartFile)
                        && !(param instanceof MultipartFile[])
                ).collect(Collectors.toList()));

        log.info("\n    [Controller start], {}, methodName->{}, IP->{}, requestParam->{},", controllerTitle, methodName, iP, requestParam);

        long begin = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        log.info("\n    [Controller end], 耗时->{}ms, result->{}", System.currentTimeMillis() - begin, JSONObject.toJSONString(result));
//        log.info("\n    [Controller end], {}, 耗时->{}ms, result->{}", controllerTitle, System.currentTimeMillis() - begin, JSONObject.toJSONString(result));
        return result;
    }

    /**
     * 获取Controller的方法名
     */

    private String getControllerMethodTitle(ProceedingJoinPoint joinPoint) {
        Method[] methods = joinPoint.getSignature().getDeclaringType().getMethods();
        for (Method method : methods) {
            if (StringUtils.equalsIgnoreCase(method.getName(), joinPoint.getSignature().getName())) {
                ControllerMethodTitle annotation = method.getAnnotation(ControllerMethodTitle.class);
                if (ObjectUtils.isNotEmpty(annotation)) {
                    return annotation.value();
                }
            }
        }
        return "该Controller的方法使用未使用注解@ControllerMethodTitle，请使用该注解说明方法作用";
    }

    /**
     * 获取目标主机的ip
     *
     * @param request
     * @return
     */
    private String getIp(HttpServletRequest request) {
        List<String> ipHeadList = Stream.of("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "X-Real-IP").collect(Collectors.toList());
        for (String ipHead : ipHeadList) {
            if (checkIP(request.getHeader(ipHead))) {
                return request.getHeader(ipHead).split(",")[0];
            }
        }
        return "0:0:0:0:0:0:0:1".equals(request.getRemoteAddr()) ? "127.0.0.1" : request.getRemoteAddr();
    }

    /**
     * 检查ip存在
     */
    private boolean checkIP(String ip) {
        return !(null == ip || 0 == ip.length() || "unknown".equalsIgnoreCase(ip));
    }

}
